#ifndef _STD_COM_H__
#define _STD_COM_H__

#include <dlcom/byunknown.hpp>
#include <dlcom/comsentry.hpp>
#define MAX_PROGIDLEN	100

namespace by {
	//////////////////////////////////////////////////////////////////////////


	inline bool operator < (const GUID& left, const GUID& right)
	{
		return memcmp(&left, &right, sizeof(GUID)) < 0;
	}

	class CUnknownImp
	{
	public:
		ULONG m_RefCount;
		CUnknownImp() :m_RefCount(0)
		{

		}
		virtual ~CUnknownImp()
		{

		}
	};

#define QIBEGIN	\
	std_method(QueryInterface)(REFGUID riid, void **ppv)	{					\

#define QIUNKNOWN	\
	if(_uuidof(IBase) == riid)											\
	{																			\
		*ppv = static_cast<IBase*>(this);									\
		AddRef();																\
		return S_OK;															\
	}																			\

#define QIUNKNOWN_(icast)														\
	if(_uuidof(IBase) == riid)											\
	{																			\
		*ppv = static_cast<IBase*>(static_cast<icast*>(this));			\
		AddRef();																\
		return S_OK;															\
	}																			\

#define QIENTRY(iface)															\
	if(_uuidof(iface) == riid)												\
	{																			\
		*ppv = static_cast<iface*>(this);										\
		AddRef();																\
		return S_OK;															\
	}																			\

#define QIENTRY_(iface, icast)													\
	if(_uuidof(iface) == riid)												\
	{																			\
		*ppv = static_cast<iface*>(static_cast<icast*>(this));					\
		AddRef();																\
		return S_OK;															\
	}																			\

#define QIEND																	\
	return E_NOINTERFACE; }														\



#define ADDREF																	\
	std_method_(ULONG, AddRef)()												\
	{																			\
		atomicadd((LONG*)(LPVOID)&this->m_RefCount);							\
		return this->m_RefCount;												\
	}																			\

#define RELEASE																	\
	std_method_(ULONG, Release)()												\
	{																			\
		atomicdel((LONG*)(LPVOID)&this->m_RefCount);							\
		if(this->m_RefCount)													\
			return this->m_RefCount;											\
		delete this;															\
		return 0;																\
	}																			\


#define UNKNOWN_IMP_SPEC(entrys) \
	QIBEGIN  QIUNKNOWN  entrys  QIEND  ADDREF  RELEASE

#define UNKNOWN_IMP_SPEC_(icast, entrys) \
	QIBEGIN  QIUNKNOWN_(icast)  entrys  QIEND  ADDREF  RELEASE

#define UNKNOWN_IMP_SPEC_MEM(entrys) \
	QIBEGIN  QIUNKNOWN  entrys  QIEND  ADDREF



#define ADDREF_EX																\
	std_method_(ULONG, AddRef)()												\
	{																			\
		atomicadd((LONG*)(LPVOID)&this->m_RefCount);								\
		return this->m_RefCount;												\
	}																			\

#define RELEASE_EX																\
	std_method_(ULONG, Release)()												\
	{																			\
		atomicdel((LONG*)(LPVOID)&this->m_RefCount);								\
		if(this->m_RefCount)													\
			return this->m_RefCount;											\
		delete this;															\
		return 0;																\
	}																			\

#define UNKNOWN_IMP_SPEC_EX(entrys) \
	QIBEGIN  QIUNKNOWN  entrys  QIEND  ADDREF_EX  RELEASE_EX


#define UNKNOWN_IMP1(i) \
	UNKNOWN_IMP_SPEC( QIENTRY(i) )
#define UNKNOWN_IMP2(i1, i2) \
	UNKNOWN_IMP_SPEC( QIENTRY(i1) QIENTRY(i2) )
#define UNKNOWN_IMP3(i1, i2, i3) \
	UNKNOWN_IMP_SPEC( QIENTRY(i1) QIENTRY(i2) QIENTRY(i3) )
#define UNKNOWN_IMP4(i1, i2, i3, i4) \
	UNKNOWN_IMP_SPEC( QIENTRY(i1) QIENTRY(i2) QIENTRY(i3) QIENTRY(i4) )
#define UNKNOWN_IMP5(i1, i2, i3, i4, i5) \
	UNKNOWN_IMP_SPEC( QIENTRY(i1) QIENTRY(i2) QIENTRY(i3) QIENTRY(i4) QIENTRY(i5) )

#define UNKNOWN_IMP1_(i) \
	UNKNOWN_IMP_SPEC_( QIENTRY(i) )
#define UNKNOWN_IMP2_(i1, i2) \
	UNKNOWN_IMP_SPEC_(i1, QIENTRY(i1) QIENTRY(i2) )
#define UNKNOWN_IMP3_(i1, i2, i3) \
	UNKNOWN_IMP_SPEC_(i1, QIENTRY(i1) QIENTRY(i2) QIENTRY(i3) )
#define UNKNOWN_IMP4_(i1, i2, i3, i4) \
	UNKNOWN_IMP_SPEC_(i1, QIENTRY(i1) QIENTRY(i2) QIENTRY(i3) QIENTRY(i4) )
#define UNKNOWN_IMP5_(i1, i2, i3, i4, i5) \
	UNKNOWN_IMP_SPEC_(i1, QIENTRY(i1) QIENTRY(i2) QIENTRY(i3) QIENTRY(i4) QIENTRY(i5) )

#define UNKNOWN_IMP1_MEM(i) \
	UNKNOWN_IMP_SPEC_MEM( QIENTRY(i) )

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////


	class IUnknown_Nondelegate
	{
	public:
		std_method(QueryInterface_Nondelegate)(REFGUID riid, void **ppv)	= 0;
		std_method_(ULONG, AddRef_Nondelegate)()							= 0;
		std_method_(ULONG, Release_Nondelegate)()							= 0;
	};

}
	


#endif
